#include "client.h"

void error_exit(const char* func)
{
	printf("%s:%m\n",func);
	exit(EXIT_FAILURE);
}

void menu()
{
    system("clear");
    puts("银行用户界面");
    puts("1.开户");
    puts("2.登录");
    puts("3.解锁");
    puts("4.退出");
}

int main()
{
    //创建socket对象
	int cli_fd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > cli_fd)
		error_exit("socket");

	//准备server的通信地址
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2323);
	addr.sin_addr.s_addr = inet_addr("39.101.73.96");
	socklen_t addrlen = sizeof(addr); 

	//连接server
	if(connect(cli_fd,(struct sockaddr*)&addr,addrlen))
		error_exit("connect");

    
    Client_Msg msg;
    msg.type = 10;      //退出指令
    for(;;)
    {
        menu();
        switch(get_cmd('1','4'))
		{
		case '1': open_acc(cli_fd);     break;       //开户
		case '2': login_acc(cli_fd);    break;       //登录
        case '3': unlock(cli_fd);       break;       //解锁
		case '4': 
        send(cli_fd,&msg,sizeof(msg),0);
        //关闭socket对象
        close(cli_fd);
        return EXIT_SUCCESS;
		}
    }
}

void open_acc(int cli_fd)
{
    system("clear");

    Client_Msg msg;
    msg.type = ACCONT_OPEN;

    printf("开户:\n");
    printf("请输入您的用户名:\n");
    get_str(msg.acc.name,sizeof(msg.acc.name));

    printf("请输入您的密码:\n");
    char pswd[10];
    get_passwd(pswd,sizeof(pswd),1);
    printf("请再次输入您的密码:\n");
    get_passwd(msg.acc.pswd,sizeof(msg.acc.pswd),1);
    if(strcmp(pswd,msg.acc.pswd))
    {
        printf("密码输入不一致,退出开户!\n");
        sleep(1);
        return;
    }

    printf("请输入您的存款金额:\n");
    scanf("%f",&(msg.acc.balance));
    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    send(cli_fd,&msg,sizeof(msg),0);

    char buf[4096];
    recv(cli_fd,buf,sizeof(buf),0);
    printf("%s\n",buf);
    sleep(1);
}

void login_acc(int cli_fd)
{
    system("clear");

    Client_Msg msg;
    msg.type = ACCONT_LOGIN;

    printf("请输入您的卡号:\n");
    scanf("%u",&(msg.acc.id));
    printf("请输入您的密码:\n");
    get_passwd(msg.acc.pswd,sizeof(msg.acc.pswd),1);

    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    //发送消息
    send(cli_fd,&msg,sizeof(msg),0);

    char buf[50];
    recv(cli_fd,buf,sizeof(buf),0);

    if(strcmp("登录成功!",buf))         //登录失败
    {
        printf("%s\n",buf);             //被锁定或账号密码不匹配或账号不存在
        sleep(1);
        return;
    }

    printf("%s\n",buf);             //登录成功
    Accont acc;
    recv(cli_fd,&acc,sizeof(Accont),0);
    sleep(1);
    login_main(cli_fd,&acc);
}

void login_menu()
{
    system("clear");
    puts("银行业务界面");
    puts("1.存钱");
    puts("2.取钱");
    puts("3.转账");
    puts("4.查询");
    puts("5.改密码");
    puts("6.注销");
    puts("7.退出账号");
}

void login_main(int cli_fd,Accont* acc)
{
    for(;;)
    {
        login_menu();
        switch(get_cmd('1','7'))
		{
		case '1': save_money(cli_fd,acc);     break;       //存钱
		case '2': take_money(cli_fd,acc);     break;       //取钱
        case '3': trans_money(cli_fd,acc);    break;       //转账
        case '4': query_acc(cli_fd,acc);      break;       //查询
        case '5': change_pswd(cli_fd,acc);    break;       //改密码
        case '6': destroy_acc(cli_fd,acc);    break;       //注销
		case '7': return;                                  //退出
		}
    }
}

void save_money(int cli_fd,Accont* acc)
{
    printf("请输入您要存入的现金:\n");
    float sum;
    scanf("%f",&sum);
    if(0 > sum)
    {
        printf("金额输入错误!\n");
        sleep(1);
        return;
    }

    Client_Msg msg;
    msg.type = ACCONT_SAVE;
    acc->balance += sum;
    msg.acc = *acc;
    sprintf(msg.buf,"%.2f",sum);

    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    send(cli_fd,&msg,sizeof(Client_Msg),0);

    char buf[50];
    recv(cli_fd,buf,sizeof(buf),0);
    printf("%s\n",buf);
}

void take_money(int cli_fd,Accont* acc)
{
    printf("请输入您要取走的现金:\n");
    float sum;
    scanf("%f",&sum);
    if(sum > acc->balance)
    {
        printf("取出金额大于您的存款!\n");
        sleep(1);
        return;
    }

    Client_Msg msg;
    msg.type = ACCONT_TAKE;
    acc->balance -= sum;
    msg.acc = *acc;
    sprintf(msg.buf,"%.2f",sum);

    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    send(cli_fd,&msg,sizeof(Client_Msg),0);

    char buf[50];
    recv(cli_fd,buf,sizeof(buf),0);
    printf("%s\n",buf);
}

void trans_money(int cli_fd,Accont* acc)
{
    Client_Msg msg;        //自己的账户
    msg.type = ACCONT_TRANS;

    printf("请输入您的转账账号:");
    size_t id;
    scanf("%u",&id);
    if(id == acc->id)
    {
        printf("您不能自己转账给自己!\n");
        sleep(1);
        return;
    }

    printf("请输入您的转账金额:");
    float sum;
    scanf("%f",&sum);
    if(sum > acc->balance)
    {
        printf("转账金额大于您的存款!\n");
        sleep(1);
        return;
    }

    msg.acc = *acc;
    msg.acc.balance -= sum;
    sprintf(msg.buf,"%u%.2f",id,sum);                 

    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    send(cli_fd,&msg,sizeof(Client_Msg),0);

    char buf[100];
    recv(cli_fd,buf,sizeof(buf),0);
    printf("%s\n",buf);
}

void query_acc(int cli_fd,Accont* acc)
{
    printf("ID:%u\n用户名:%s  密码:%s\n金额:%.2f 锁定状态:%s 剩余密码错误机会:%u\n"
    ,acc->id,acc->name,acc->pswd,acc->balance,
    acc->flag_lock ? "锁定":"未锁定",acc->lock_times);
    anykey_continue();
}

void change_pswd(int cli_fd,Accont* acc)
{
    Client_Msg msg;
    msg.type = ACCONT_MODIFY;

    printf("请输入原密码:\n");
    char old_pswd[10];
    get_passwd(old_pswd,sizeof(old_pswd),1);

    if(strcmp(old_pswd,acc->pswd))
    {
        printf("密码输入错误!\n");
        sleep(1);
        return;
    }

    printf("请输入修改密码:\n");
    char new_pswd[10];
    get_passwd(old_pswd,sizeof(old_pswd),1);        //利用原来不用的老密码空间
    printf("请再次输入修改密码:\n");
    get_passwd(new_pswd,sizeof(new_pswd),1);

    if(strcmp(old_pswd,new_pswd))
    {
        printf("密码输入不一致!\n");
        sleep(1);
        return;
    }
    strcpy(acc->pswd,new_pswd);

    msg.acc = *acc;

    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    send(cli_fd,&msg,sizeof(Client_Msg),0);

    char buf[30];
    recv(cli_fd,buf,sizeof(buf),0);
    printf("%s\n",buf);
}

void destroy_acc(int cli_fd,Accont* acc)
{
    printf("请输入您的卡号:\n");
    size_t id;
    scanf("%u",&id);
    printf("请输入您的密码:\n");
    char pswd[10];
    get_passwd(pswd,sizeof(pswd),1);

    if(id != acc->id || strcmp(pswd,acc->pswd))
    {
        printf("信息输入错误!\n");
        sleep(1);
        return;
    }

    printf("您确定要销号么?\n");
    if(yes_or_no())
    {
        Client_Msg msg;
        msg.type = ACCONT_DESTROY;
        msg.acc = *acc;

        strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
        send(cli_fd,&msg,sizeof(Client_Msg),0);

        char buf[30];
        recv(cli_fd,buf,sizeof(buf),0);
        printf("%s\n",buf);
        return;
    }
    printf("取消操作!\n");
    sleep(1);
    return;
}

void unlock(int cli_fd)
{
    Client_Msg msg;
    msg.type = ACCONT_UNLOCK;

    printf("请输入您的ID:\n");
    scanf("%u",&(msg.acc.id));

    printf("请输入您的密码:\n");
    get_passwd(msg.acc.pswd,sizeof(msg.acc.pswd),1);

    printf("请输入您的用户名:\n");
    get_str(msg.acc.name,sizeof(msg.acc.name));

    strcat(msg.buf,"\n");               //防止粘包 设置的数据结束标志位
    send(cli_fd,&msg,sizeof(Client_Msg),0);

    char buf[30];
    recv(cli_fd,buf,sizeof(buf),0);
    printf("%s\n",buf);
    sleep(1);
}
